#if DEBUG

using System.Xml.Linq;
using Castle.DynamicProxy;
using FluentlyXml.Core;
using FluentlyXml.Core.DSL;
using FluentlyXml.UnitTests.Core.TestObjects;
using FluentlyXml.UnitTests.Helpers;
using NUnit.Framework;
using System.Linq;

namespace FluentlyXml.UnitTests.Core
{
	public class FooSerializationTests
	{
		public class When_serializing_a_foo : FooSerializationTestBase
		{
			private string _xml;

			[SetUp]
			public void When()
			{
				_xml = _serializer.Serialize(_testFoo).ToString();
			}

			[Test]
			public void Then_it_serializes_the_bars()
			{
				Assert.That(_xml, Is.StringContaining("<Bar>"));
			}

			[Test]
			public void Then_it_serializes_the_subfoos()
			{
				Assert.That(_xml, Is.StringContaining("<SubFoos>"));
			}
		}

		public class When_deserializing_a_foo : FooSerializationTestBase
		{
			private Foo _deserializedFoo;

			[SetUp]
			public void When()
			{
				var xml = _serializer.Serialize(_testFoo).ToString();
				_deserializedFoo = _deserializer.Deserialize<Foo>(xml);
			}

			[Test]
			public void Then_it_deserializes_to_an_equivalent_object_graph()
			{
				EqualityTester.AssertEqual(_testFoo, _deserializedFoo);
			}
		}

		public class When_serializing_proxied_foo_hierarchy : FooSerializationTestBase
		{
			private XElement _xml;

			[SetUp]
			public void When()
			{
				_testFoo.SubFoos.Clear();

				var generator = new ProxyGenerator();
				var proxiedFood = (Foo) generator.CreateClassProxy(typeof (Foo));
				proxiedFood.Name = "I Am A Proxy!";

				_testFoo.SubFoos.Add(proxiedFood);

				_xml = _serializer.Serialize(_testFoo);
			}

			[Test]
			public void then_it_serialized_the_sub_foo_as_a_foo()
			{
				Assert.That(_xml.Element("SubFoos").Elements().First().Name.ToString(), Is.EqualTo("Foo"));
			}
		}

		[TestFixture]
		public class FooSerializationTestBase
		{
			protected Foo _testFoo;
			protected IFluentSerializer _serializer;
			protected IFluentDeserializer _deserializer;

			public FooSerializationTestBase()
			{
				var factory = new FluentSerializerFactory(x =>
				{
					x.ApplyConfigFrom<FooSerialization>();
				});

				_testFoo = Foo.GetTestFoo();

				_serializer = factory.CreateSerializer();
				_deserializer = factory.CreateDeserializer();
			}
		}

		public class FooSerialization : FluentSerializationSpec
		{
			public FooSerialization()
			{
				WhenSerializing<Foo>()
					.SerializeAllAncestorsAsThisType()
					.Serialize(p => p.Parent).Using(p => p.Parent != null ? p.Parent.Id : null);

				WhenDeserializing<Foo>()
					.Ignore(p => p.Parent)
					.AfterDeserialization(FixUpParentChildRelationships);
			}

			private void FixUpParentChildRelationships(Foo obj)
			{
				foreach (var child in obj.SubFoos)
				{
					child.Parent = obj;
				}
			}
		}
	}
}

#endif